package org.jsola.hr.service.impl;

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.jsola.core.Page;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.common.HrKit;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.IAttendPeopleMonthlyStatDAO;
import org.jsola.hr.dto.AttendPeopleMonthlyStatAddDTO;
import org.jsola.hr.dto.AttendPeopleMonthlyStatUpdateDTO;
import org.jsola.hr.dto.AttendPeriodStatAddDTO;
import org.jsola.hr.dto.PunchStatusUpdateDTO;
import org.jsola.hr.entity.*;
import org.jsola.hr.exception.HrException;
import org.jsola.hr.query.*;
import org.jsola.hr.service.*;
import org.jsola.hr.vo.*;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zhr
 */
@Service("hrAttendPeopleMonthlyStatServiceImpl")
public class AttendPeopleMonthlyStatServiceImpl implements IAttendPeopleMonthlyStatService {

    @Autowired
    private IAttendPeopleMonthlyStatDAO attendPeopleMonthlyStatDAO;
    @Autowired
    private IDepInfoService depInfoService;
    @Autowired
    private IAttendPunchRecordService attendPunchRecordService;
    @Autowired
    private IAttendPeriodStatService attendPeriodStatService;
    @Autowired
    private IAttendPlanService attendPlanService;
    @Autowired
    private IEmpInfoService empInfoService;
    @Autowired
    private IAttendPunchTimeService attendPunchTimeService;
    @Autowired
    private IAttendCalendarService attendCalendarService;
    @Autowired
    private IGregorianCalendarService gregorianCalendarService;
    @Autowired
    private IAttendPeopleMonthlyStatService attendPeopleMonthlyStatService;
    @Autowired
    private IEmpDepService empDepService;

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public AttendPeopleMonthlyStatVO save(AttendPeopleMonthlyStatAddDTO attendPeopleMonthlyStatAddDTO, TokenUser tokenUser) {
        // 转DO
        AttendPeopleMonthlyStatDO attendPeopleMonthlyStatDO = attendPeopleMonthlyStatAddDTO.to(AttendPeopleMonthlyStatDO.class);
        // 保存
        attendPeopleMonthlyStatDO = save(attendPeopleMonthlyStatDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return attendPeopleMonthlyStatDO.to(AttendPeopleMonthlyStatVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(AttendPeopleMonthlyStatUpdateDTO attendPeopleMonthlyStatUpdateDTO, TokenUser tokenUser) {
        //转DO
        AttendPeopleMonthlyStatDO attendPeopleMonthlyStatDO = attendPeopleMonthlyStatUpdateDTO.to(AttendPeopleMonthlyStatDO.class);
        //根据主键更新，只更新非null值
        return updateByIdSelective(attendPeopleMonthlyStatDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... attendPeopleMonthlyStatIds) {
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) attendPeopleMonthlyStatIds);
    }


    @Override
    public AttendPeopleMonthlyStatVO selectById(String attendPeopleMonthlyStatId, String siteId) {
        AttendPeopleMonthlyStatDO attendPeopleMonthlyStatDO = selectDOById(attendPeopleMonthlyStatId, siteId);
        if (attendPeopleMonthlyStatDO == null) {
            return null;
        }
        return attendPeopleMonthlyStatDO.to(AttendPeopleMonthlyStatVO.class);
    }

    @Override
    public List<AttendPeopleMonthlyStatListVO> select(AttendPeopleMonthlyStatQuery attendPeopleMonthlyStatQuery, String siteId) {
        List<AttendPeopleMonthlyStatDO> attendPeopleMonthlyStatDOList = selectDO(attendPeopleMonthlyStatQuery, siteId);
        if(CollectionUtils.isEmpty(attendPeopleMonthlyStatDOList)) {
            return attendPeopleMonthlyStatDOList == null ? null : new ArrayList<>();
        }
        return attendPeopleMonthlyStatDOList.stream()
                .map(attendPeopleMonthlyStatDO -> attendPeopleMonthlyStatDO.to(AttendPeopleMonthlyStatListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(AttendPeopleMonthlyStatQuery attendPeopleMonthlyStatQuery, String siteId) {
        Example example = buildExample(attendPeopleMonthlyStatQuery,siteId);
        return attendPeopleMonthlyStatDAO.selectCountByExample(example);
    }

    @Override
    public Page<AttendPeopleMonthlyStatListVO> selectPage(AttendPeopleMonthlyStatQuery attendPeopleMonthlyStatQuery, String siteId) {

        // 查询条件，公司ID
        attendPeopleMonthlyStatQuery.setCompanyId(attendPeopleMonthlyStatQuery.getCompanyId());
        attendPeopleMonthlyStatQuery.addOrder("gmtCreate", true);
        Example example = buildExample(attendPeopleMonthlyStatQuery,siteId);
        Page<AttendPeopleMonthlyStatDO> page = attendPeopleMonthlyStatDAO.selectPageByExample(example,
                attendPeopleMonthlyStatQuery.getPageNo(),
                attendPeopleMonthlyStatQuery.getPageSize());

        return page.to(AttendPeopleMonthlyStatListVO.class);
    }

    @Override
    public AttendPeopleMonthlyStatDO selectDOById(String attendPeopleMonthlyStatId, String siteId) {
        return listById(attendPeopleMonthlyStatId, siteId);
    }

    @Override
    public List<AttendPeopleMonthlyStatDO> selectDO(AttendPeopleMonthlyStatQuery attendPeopleMonthlyStatQuery, String siteId) {
        Example example = buildExample(attendPeopleMonthlyStatQuery,siteId);
        return attendPeopleMonthlyStatDAO.selectByExample(example);
    }

    @Override
    public List<AttendPeopleDailyListVO> monthlyDetail(AttendPeopleDailyQuery attendPeopleDailyQuery, String siteId) {

        List<AttendPeopleDailyListVO> dailyList = new ArrayList<>();

        // 当前月份一同有多少天
        int year = Integer.valueOf(attendPeopleDailyQuery.getYearlyMonthly().split("-")[0]).intValue();
        int month = Integer.valueOf(attendPeopleDailyQuery.getYearlyMonthly().split("-")[1]).intValue();
        int days = HrKit.getDays(year, month);

        // 初始化当月的
        for (int i = 1; i <= days; i++) {

            String dayStr = "";
            if (i < 10) {
                dayStr = "0" + i;
            }
            else {
                dayStr = i + "";
            }

            AttendPeopleDailyListVO vo = new AttendPeopleDailyListVO();
            vo.setYearly(year+"");
            vo.setMonthly(attendPeopleDailyQuery.getYearlyMonthly().split("-")[1]);
            vo.setDaily(dayStr);
            vo.setOnWork(0);
            vo.setOffWork(0);

            dailyList.add(vo);
        }

        // 查询员工当前月的考勤记录
        AttendPunchRecordQuery attendPunchRecordQuery = new AttendPunchRecordQuery();
        attendPunchRecordQuery.setYear(attendPeopleDailyQuery.getYearlyMonthly().split("-")[0]);
        attendPunchRecordQuery.setMonth(attendPeopleDailyQuery.getYearlyMonthly().split("-")[1]);
        attendPunchRecordQuery.setEmpInfoId(attendPeopleDailyQuery.getEmpInfoId());

        List<AttendPunchRecordDO> doList = attendPunchRecordService.selectDO(attendPunchRecordQuery, siteId);

        for (int i = 0; i < dailyList.size(); i++) {

            AttendPeopleDailyListVO vo = dailyList.get(i);

            for (AttendPunchRecordDO record: doList) {

                if (vo.getDaily().equals(record.getDay())
                        && vo.getMonthly().equals(record.getMonth())
                        && vo.getYearly().equals(record.getYear())) {
                    // 打卡类型 ; 0-无效打卡,1-上班打卡,2-下班打卡,3-完成打卡
                    // 打卡状态 ; 0-缺卡,1-正常,2-迟到,3-早退
                    // 上班
                    if (record.getPunchType() == 1) {
                         vo.setOnWork(record.getPunchStatus());
                         vo.setOnWorkId(record.getId());
                    }
                    // 下班
                    if (record.getPunchType() == 2) {
                         vo.setOffWork(record.getPunchStatus());
                         vo.setOffWorkId(record.getId());
                    }

                    vo.setEmpInfoId(record.getEmpInfoId());
                }
            }
        }

        if (dailyList.size() > 0) {
            for (int i = 0; i < dailyList.size(); i++) {

                AttendPeopleDailyListVO vo = dailyList.get(i);
                // 查询当前日期星期几
                String ymd = attendPeopleDailyQuery.getYearlyMonthly() + "-" + vo.getDaily();
                String week = null;
                try {
                    week = HrKit.getWeek(DateUtils.parseDate(ymd, "yyyy-MM-dd"));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                if (week.equals("星期六")) {
                    vo.setDaily("六");
                }
                else if (week.equals("星期日")) {
                    vo.setDaily("日");
                }
            }
        }

        return dailyList;
    }

    /**
     * 打卡详情
     *
     * @param attendDailyPeriodQuery
     * @param siteId
     * @return
     */
    @Override
    public List<AttendDailyPeriodVO> attendDailyPeriodOfMonth(AttendDailyPeriodQuery attendDailyPeriodQuery, String siteId) {

        List<AttendDailyPeriodVO> periodList = new ArrayList<>();

        // 查询考勤打卡时间段统计
        AttendPeriodStatQuery attendPeriodStatQuery = new AttendPeriodStatQuery();
        attendPeriodStatQuery.setPeopleMonthlyStatId(attendDailyPeriodQuery.getPeopleMonthlyStatId());
        List<AttendPeriodStatDO> attendPeriodStatList = attendPeriodStatService.selectDO(attendPeriodStatQuery, siteId);
        if (attendPeriodStatList.size() <= 0) {
            return periodList;
        }

        Map<String, List<String>> periodMap = new HashMap<String, List<String>>();

        // 将时间段放入MAP中
        for (AttendPeriodStatDO attendPeriodStat : attendPeriodStatList) {

            List<String> recordIds = periodMap.get(attendPeriodStat.getPeriod());
            if (recordIds == null) {
                recordIds = new ArrayList<>();
                recordIds.add(attendPeriodStat.getAttendRecordId());
                periodMap.put(attendPeriodStat.getPeriod(), recordIds);
            }
            else {
                recordIds.add(attendPeriodStat.getAttendRecordId());
                periodMap.put(attendPeriodStat.getPeriod(), recordIds);
            }
        }

        // 遍历map ，获取时间段
        for(Map.Entry<String, List<String>> entry : periodMap.entrySet()) {

            // 每日多条打卡记录
            Map<String, List<AttendDailyStatusVO>> dailyMap = new HashMap<String, List<AttendDailyStatusVO>>();

            // 时段
            String period = entry.getKey();
            // 考勤记录ids
            List<String> recordIds = entry.getValue();

            for (String recordId : recordIds) {
                // 根据ID查询考勤记录
                AttendPunchRecordDO attendPunchRecordDO = attendPunchRecordService.selectDOById(recordId, siteId);
                if (attendPunchRecordDO != null) {
                    String ymd = attendPunchRecordDO.getYear() + "-" + attendPunchRecordDO.getMonth() + "-" + attendPunchRecordDO.getDay();

                    List<AttendDailyStatusVO> dailyList = dailyMap.get(ymd);
                    if (dailyList == null) {
                        dailyList = new ArrayList<>();
                    }

                    AttendDailyStatusVO attendDailyStatusVO = new AttendDailyStatusVO();
                    // 上班或下班状态-展示
                    attendDailyStatusVO.setWorkStatusStr("");
                    // 上班或下班状态
                    attendDailyStatusVO.setWorkStatus(attendPunchRecordDO.getPunchStatus());
                    // 上班或下班ID
                    attendDailyStatusVO.setWorkId(attendPunchRecordDO.getId());
                    // 时间点
//                    attendDailyStatusVO.setTimePoint(attendPunchRecordDO.getStandardTime());

                    attendDailyStatusVO.setAttendPlanId(attendPunchRecordDO.getAttendPlanId());

                    attendDailyStatusVO.setPunchType(attendPunchRecordDO.getPunchType());

                    dailyList.add(attendDailyStatusVO);

                    dailyMap.put(ymd, dailyList);
                }
            }

            // dailyMap 排序
            if (dailyMap.size() > 0) {
                dailyMap = sortMapByKey(dailyMap);
            }

            // 每日考勤日期
            List<AttendDailyDateVO> dailyDateList = new ArrayList<>();

            // 遍历dailyMap
            for(Map.Entry<String, List<AttendDailyStatusVO>> daily : dailyMap.entrySet()) {

                String ymd = daily.getKey();
                List<AttendDailyStatusVO> dataList = daily.getValue();

                AttendDailyDateVO attendDailyDateVO = new AttendDailyDateVO();
                attendDailyDateVO.setYearly(ymd.split("-")[0]);
                attendDailyDateVO.setMonthly(ymd.split("-")[1]);
                attendDailyDateVO.setDaily(ymd.split("-")[2]);
                attendDailyDateVO.setDailyStatusList(dataList);

                dailyDateList.add(attendDailyDateVO);
            }

            AttendDailyPeriodVO attendDailyPeriodVO = new AttendDailyPeriodVO();
            attendDailyPeriodVO.setPeriod(period);
            attendDailyPeriodVO.setDailyDateList(dailyDateList);

            periodList.add(attendDailyPeriodVO);
        }

        if (periodList.size() > 0) {

            for (AttendDailyPeriodVO attendDailyPeriod : periodList) {

                List<String> timePoint = new ArrayList<>();

                String period = attendDailyPeriod.getPeriod();

                String[] periodArr = period.split(";");
                for (int i = 0; i < periodArr.length; i++) {
                    timePoint.add(periodArr[i].split("-")[0]);
                    timePoint.add(periodArr[i].split("-")[1]);
                }

                List<AttendDailyDateVO> dailyDateList = attendDailyPeriod.getDailyDateList();
                if (dailyDateList != null && dailyDateList.size() > 0) {

                    for (int i = 0; i < dailyDateList.size(); i++) {

                        AttendDailyDateVO attendDailyDate = dailyDateList.get(i);

                        if (timePoint.size()  > attendDailyDate.getDailyStatusList().size()) {

                            List<AttendDailyStatusVO> dailyStatusList = attendDailyDate.getDailyStatusList();
                            List<AttendDailyStatusVO> dailyStatusTmp = attendDailyDate.getDailyStatusList();
                            if (dailyStatusList != null && dailyStatusList.size() > 0) {

                                for (String point : timePoint) {

                                    boolean isHash = false;
                                    for (int j = 0; j < dailyStatusList.size(); j++) {
                                        AttendDailyStatusVO attendDailyStatusVO = dailyStatusList.get(j);
                                        if (attendDailyStatusVO.getTimePoint().equals(point)) {
                                            // dailyStatusTmp.add(attendDailyStatusVO);
                                            isHash = true;
                                            break;
                                        }
                                    }

                                    // 添加集合
                                    if (!isHash) {

                                        // 当前的查询时间是否当天
                                        String currentDate = DateFormatUtils.format(new Date(), "yyyy-MM-dd");
                                        String dateStr = attendDailyDate.getYearly() + "-" + attendDailyDate.getMonthly() + "-" + attendDailyDate.getDaily();
                                        if (currentDate.equals(dateStr)) {
                                            AttendDailyStatusVO status = new AttendDailyStatusVO();
                                            status.setTimePoint(point);
                                            status.setWorkId("");
                                            status.setWorkStatus(0);
                                            status.setWorkStatusStr("-");
                                            status.setAttendPlanId("");
                                            status.setPunchType(0);
                                            dailyStatusTmp.add(status);
                                        }
                                        else {
                                            AttendDailyStatusVO status = new AttendDailyStatusVO();
                                            status.setTimePoint(point);
                                            status.setWorkId("");
                                            status.setWorkStatus(6);
                                            status.setWorkStatusStr("异常");
                                            status.setAttendPlanId("");
                                            status.setPunchType(0);
                                            dailyStatusTmp.add(status);
                                        }
                                    }
                                }

                                // 排序
                                // dailyStatusTmp.sort(Comparator.comparing(AttendDailyStatusVO::getTimePoint));

                                Collections.sort(dailyStatusTmp, new Comparator<AttendDailyStatusVO>() {

                                    @Override
                                    public int compare(AttendDailyStatusVO o1, AttendDailyStatusVO o2) {

                                        int time1 = Integer.valueOf(o1.getTimePoint().replace(":", "")).intValue();
                                        int time2 = Integer.valueOf(o2.getTimePoint().replace(":", "")).intValue();

                                        return time1 - time2;
                                    }
                                });

                                attendDailyDate.setDailyStatusList(dailyStatusTmp);
                                dailyStatusTmp = new ArrayList<>();
                            }
                        }
                    }
                }
            }
        }

        return periodList;
    }


    /**
     * 使用 Map按key进行排序
     * @param map
     * @return
     */
    private Map<String, List<AttendDailyStatusVO>> sortMapByKey(Map<String, List<AttendDailyStatusVO>> map) {
        if (map == null || map.isEmpty()) {
            return null;
        }

        Map<String, List<AttendDailyStatusVO>> sortMap = new TreeMap<String, List<AttendDailyStatusVO>>(new MapKeyComparator());
        sortMap.putAll(map);
        return sortMap;
    }

    class MapKeyComparator implements Comparator<String>{

        @Override
        public int compare(String str1, String str2) {

            return str1.compareTo(str2);
        }
    }


    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int updatePunchStatus(PunchStatusUpdateDTO punchStatusUpdateDTO, TokenUser tokenUser) {

        // 查询考勤打卡记录
        AttendPunchRecordQuery attendPunchRecordQuery = new AttendPunchRecordQuery();
        attendPunchRecordQuery.setAttendPlanId(punchStatusUpdateDTO.getAttendPlanId());
        attendPunchRecordQuery.setEmpInfoId(punchStatusUpdateDTO.getEmpInfoId());
        attendPunchRecordQuery.setYear(punchStatusUpdateDTO.getYearly());
        attendPunchRecordQuery.setMonth(punchStatusUpdateDTO.getMonthly());
        attendPunchRecordQuery.setDay(punchStatusUpdateDTO.getDaily());
//        attendPunchRecordQuery.setStandardTime(punchStatusUpdateDTO.getTimePoint());
        List<AttendPunchRecordDO> attendPunchRecordList = attendPunchRecordService.selectDO(attendPunchRecordQuery, tokenUser.getSiteId());
        if (attendPunchRecordList.size() > 0) {

            AttendPunchRecordDO attendPunchRecordDO = new AttendPunchRecordDO();
            attendPunchRecordDO.setId(attendPunchRecordList.get(0).getId());
            attendPunchRecordDO.setPunchStatus(punchStatusUpdateDTO.getWorkStatus());

            return attendPunchRecordService.updateByIdSelective(attendPunchRecordDO, tokenUser.getSiteId(), tokenUser.getUserId());
        }
        else {
            // 查询考勤规则
            AttendPlanVO attendPlanVO = attendPlanService.selectById(punchStatusUpdateDTO.getAttendPlanId(), tokenUser.getSiteId());

            if (attendPlanVO == null) {
                throw new HrException("考勤规则不存在");
            }

            // 查询员工信息
            EmpInfoDO empInfoDO = empInfoService.selectDOById(punchStatusUpdateDTO.getEmpInfoId(), tokenUser.getSiteId());
            if (empInfoDO == null) {
                throw new HrException("员工信息不存在");
            }

            AttendPunchRecordDO attendPunchRecordDO = new AttendPunchRecordDO();
            attendPunchRecordDO.setId(UUID.randomUUID().toString().replace("-", ""));
            attendPunchRecordDO.setCompanyId(attendPlanVO.getCompanyId());
            attendPunchRecordDO.setCompanyName(attendPlanVO.getCompanyName());
            attendPunchRecordDO.setDeptId("");
            attendPunchRecordDO.setDeptName("");
            attendPunchRecordDO.setEmpInfoId(empInfoDO.getId());
            attendPunchRecordDO.setEmpInfoName(empInfoDO.getName());
            attendPunchRecordDO.setAttendPlanId(attendPlanVO.getId());
            attendPunchRecordDO.setAttendPlanName(attendPlanVO.getName());
            attendPunchRecordDO.setYear(punchStatusUpdateDTO.getYearly());
            attendPunchRecordDO.setMonth(punchStatusUpdateDTO.getMonthly());
            attendPunchRecordDO.setDay(punchStatusUpdateDTO.getDaily());
            int punchType = 0;
            if (punchStatusUpdateDTO.getWorkStatus() == 2) {
                punchType = 1;
            }
            else if (punchStatusUpdateDTO.getWorkStatus() == 2) {
                punchType = 2;
            }

            attendPunchRecordDO.setPunchType(punchType);
//            attendPunchRecordDO.setStandardTime(punchStatusUpdateDTO.getTimePoint());
            attendPunchRecordDO.setPunchTime(null);
            attendPunchRecordDO.setPunchStatus(punchStatusUpdateDTO.getWorkStatus());
            // attendPunchRecordDO.setMinute(punchStatusUpdateDTO.getMinute());
            attendPunchRecordDO.setDecisionDesc("");
            attendPunchRecordDO.setCoordinate("");
            attendPunchRecordDO.setLocation("");
            attendPunchRecordDO.setPunchWifi("");
            attendPunchRecordDO.setPunchSource(4);
            attendPunchRecordDO.setIsMakeUp(false);
            attendPunchRecordDO.setCreateUserId(tokenUser.getUserId());
            attendPunchRecordDO.setGmtCreate(new Date());
            attendPunchRecordDO.setModifiedUserId(tokenUser.getUserId());
            attendPunchRecordDO.setGmtModified(new Date());
            attendPunchRecordDO.setSiteId(tokenUser.getSiteId());
            attendPunchRecordDO.setValid(true);

            attendPunchRecordService.save(attendPunchRecordDO, tokenUser.getSiteId(), tokenUser.getUserId());
        }

        return 1;
    }

    /**
     * 考勤打卡月统计
     *
     * @param attendPunchRecordVO 考勤记录
     * @param period 时间段
     * @param tokenUser 当前用户
     * @return
     */
    @Override
    public int monthlyStat(AttendPunchRecordVO attendPunchRecordVO, String period, TokenUser tokenUser) {

        // 查询打卡人员月统计 ,根据公司ID、考勤规则ID、员工ID、年、月、查询
        AttendPeopleMonthlyStatQuery attendPeopleMonthlyStatQuery = new AttendPeopleMonthlyStatQuery();

        attendPeopleMonthlyStatQuery.setCompanyId(attendPunchRecordVO.getCompanyId());
        attendPeopleMonthlyStatQuery.setAttendPlanId(attendPunchRecordVO.getAttendPlanId());
        attendPeopleMonthlyStatQuery.setEmpInfoId(attendPunchRecordVO.getEmpInfoId());
        attendPeopleMonthlyStatQuery.setYearly(attendPunchRecordVO.getYear());
        attendPeopleMonthlyStatQuery.setMonthly(attendPunchRecordVO.getMonth());

        List<AttendPeopleMonthlyStatDO> monthlyStatList = this.selectDO(attendPeopleMonthlyStatQuery, tokenUser.getSiteId());
        String peopleMonthlyStatId = "";
        // 如果没有则新增
        if (monthlyStatList.size() <= 0) {

            // 查询员工所在部门
            DepInfoDO depInfo = this.getDepInfo(attendPunchRecordVO.getEmpInfoId(), tokenUser.getSiteId());

            AttendPeopleMonthlyStatAddDTO attendPeopleMonthlyStatAddDTO = new AttendPeopleMonthlyStatAddDTO();

            attendPeopleMonthlyStatAddDTO.setCompanyId(attendPunchRecordVO.getCompanyId());
            attendPeopleMonthlyStatAddDTO.setCompanyName(attendPunchRecordVO.getCompanyName());
            attendPeopleMonthlyStatAddDTO.setDeptId(depInfo != null ? depInfo.getId() : "");
            attendPeopleMonthlyStatAddDTO.setDeptName(depInfo != null ? depInfo.getName() : "");
            attendPeopleMonthlyStatAddDTO.setAttendPlanId(attendPunchRecordVO.getAttendPlanId());
            attendPeopleMonthlyStatAddDTO.setEmpInfoId(attendPunchRecordVO.getEmpInfoId());
            attendPeopleMonthlyStatAddDTO.setEmpInfoName(attendPunchRecordVO.getEmpInfoName());
            attendPeopleMonthlyStatAddDTO.setJobNumber("");
            attendPeopleMonthlyStatAddDTO.setYearly(attendPunchRecordVO.getYear());
            attendPeopleMonthlyStatAddDTO.setMonthly(attendPunchRecordVO.getMonth());
            // 应出勤天数
            attendPeopleMonthlyStatAddDTO.setShouldWorkDays(0);
            // 出勤天数
            attendPeopleMonthlyStatAddDTO.setAttendDays(1);
            // 休息天数
            attendPeopleMonthlyStatAddDTO.setRestDays(0);
            // 迟到次数
            if (attendPunchRecordVO.getPunchStatus() == 2) {
                attendPeopleMonthlyStatAddDTO.setLateCounts(1);
            }
            else {
                attendPeopleMonthlyStatAddDTO.setLateCounts(0);
            }
            // 上班缺卡次数
            attendPeopleMonthlyStatAddDTO.setOnWorkMissCounts(0);
            // 下班缺卡次数
            attendPeopleMonthlyStatAddDTO.setOffWorkMissCounts(0);
            // 旷工天数
            attendPeopleMonthlyStatAddDTO.setAbsenteeismDays(new BigDecimal("0"));
            // 请假天数
            attendPeopleMonthlyStatAddDTO.setLeaveDays(new BigDecimal("0"));

            // 应出勤天数
            int shouldWorkDays = attendPeopleMonthlyStatService.calShoutWorkDays(attendPunchRecordVO.getAttendPlanId(),
                                        attendPunchRecordVO.getYear(), attendPunchRecordVO.getMonth(), tokenUser.getSiteId());

            attendPeopleMonthlyStatAddDTO.setShouldWorkDays(shouldWorkDays);

            AttendPeopleMonthlyStatVO attendPeopleMonthlyStatVO = this.save(attendPeopleMonthlyStatAddDTO ,tokenUser);
            peopleMonthlyStatId = attendPeopleMonthlyStatVO.getId();
        }
        // 更新
        else {
            AttendPeopleMonthlyStatDO attendPeopleMonthlyStatDO = new AttendPeopleMonthlyStatDO();

            attendPeopleMonthlyStatDO.setId(monthlyStatList.get(0).getId());

            // 最后一次更新日期和当前的日期不一样则增加
            String lastDateStr = DateFormatUtils.format(monthlyStatList.get(0).getGmtModified(), "yyyy-MM-dd");
            String currentDateStr = attendPunchRecordVO.getYear() + "-" + attendPunchRecordVO.getMonth() + "-" + attendPunchRecordVO.getDay();
            if (!lastDateStr.equals(currentDateStr)) {
                // 出勤天数
                attendPeopleMonthlyStatDO.setAttendDays(monthlyStatList.get(0).getAttendDays() + 1);
            }
            // 迟到次数
            if (attendPunchRecordVO.getPunchStatus() == 2) {
                attendPeopleMonthlyStatDO.setLateCounts(monthlyStatList.get(0).getLateCounts() + 1);
            }

            attendPeopleMonthlyStatDO.setGmtModified(new Date());

            attendPeopleMonthlyStatDAO.updateByPrimaryKeySelective(attendPeopleMonthlyStatDO);

            peopleMonthlyStatId = attendPeopleMonthlyStatDO.getId();
        }

        // 考勤打卡时间段统计
        // hr_attend_period_stat
        AttendPeriodStatAddDTO attendPeriodStatAddDTO = new AttendPeriodStatAddDTO();
        attendPeriodStatAddDTO.setPeopleMonthlyStatId(peopleMonthlyStatId);
        attendPeriodStatAddDTO.setCompanyId(attendPunchRecordVO.getCompanyId());
        attendPeriodStatAddDTO.setAttendPlanId(attendPunchRecordVO.getAttendPlanId());
        attendPeriodStatAddDTO.setEmpInfoId(attendPunchRecordVO.getEmpInfoId());
        attendPeriodStatAddDTO.setAttendPunchTimeId("");
        attendPeriodStatAddDTO.setPeriod(period);
        attendPeriodStatAddDTO.setYearly(attendPunchRecordVO.getYear());
        attendPeriodStatAddDTO.setMonthly(attendPunchRecordVO.getMonth());
        attendPeriodStatAddDTO.setAttendRecordId(attendPunchRecordVO.getId());
        attendPeriodStatService.save(attendPeriodStatAddDTO, tokenUser);

        return 0;
    }

    /**
     * 计算应出勤天数
     *
     * @param attendPlanId
     * @param yearly
     * @param monthly
     * @param siteId
     * @return
     */
    @Override
    public int calShoutWorkDays(String attendPlanId, String yearly, String monthly, String siteId) {

        int shoutWorkDays = 0;

        // 查询考勤打卡时间
        AttendPunchTimeQuery attendPunchTimeQuery = new AttendPunchTimeQuery();
        attendPunchTimeQuery.setAttendPlanId(attendPlanId);
        List<AttendPunchTimeDO> attendPunchTimeList = attendPunchTimeService.selectDO(attendPunchTimeQuery, siteId);
        if (attendPunchTimeList.size() <= 0) {
            return shoutWorkDays;
        }

        // 过滤需要打卡的星期数
        Set<String> workWeekSet = new HashSet<>();

        attendPunchTimeList.forEach(attendPunchTime -> {
            List<String> workWeekList = JSON.parseArray(attendPunchTime.getWorkWeekJson(), String.class);
            if (workWeekList != null && workWeekList.size() > 0) {
                workWeekList.forEach(workWeek -> {
                    workWeekSet.add(workWeek);
                });
            }
        });

        // 不需要打卡的日期
        List<String> noNeedPunchDay = new ArrayList<>();

        // 考勤规则下是否有不需要打卡的特殊日期
        AttendCalendarQuery attendCalendarQuery = new AttendCalendarQuery();
        attendCalendarQuery.setAttendPlanId(attendPlanId);
        // 是否考勤 1-是,0-否
        attendCalendarQuery.setNeedAttend(false);
        List<AttendCalendarDO> calendarList = attendCalendarService.selectDO(attendCalendarQuery, siteId);
        if (calendarList != null && calendarList.size() > 0) {
            for (AttendCalendarDO calendar : calendarList) {
                String noNeedDay = calendar.getYear() + "-" + calendar.getMonth() + "-" + calendar.getDay();
                noNeedPunchDay.add(noNeedDay);
            }
        }

        // 法定节假日不需要打卡
        GregorianCalendarQuery gregorianCalendarQuery = new GregorianCalendarQuery();
        // 1-工作日,2-休息日,3-法定节假日
        gregorianCalendarQuery.setDateTypeNotEq(1);
        List<GregorianCalendarDO> greCalendarList = gregorianCalendarService.selectDO(gregorianCalendarQuery, siteId);
        if (greCalendarList != null && greCalendarList.size() > 0) {
            for (GregorianCalendarDO gregorianCalendar : greCalendarList) {
                String noNeedDay = gregorianCalendar.getYearly() + "-" + gregorianCalendar.getMonthly() + "-" + gregorianCalendar.getDaily();
                noNeedPunchDay.add(noNeedDay);
            }
        }

        // 获取某个月有多少天
        int yearlyInt = Integer.valueOf(yearly).intValue();
        int monthlyInt = Integer.valueOf(monthly).intValue();
        int monthDays = HrKit.getDays(yearlyInt, monthlyInt);

        for (int i = 1; i <= monthDays; i++) {

            // 获取今天是星期几
            String ymd = "";
            String day = i + "";
            if (i < 10) {
                day = "0" + day;
            }
            ymd = yearly + "-" + monthly + "-" + day;

            // 不需要出勤的日期
            boolean flag = false;
            if (noNeedPunchDay != null && noNeedPunchDay.size() > 0) {
                for (String noNeedDay : noNeedPunchDay) {
                    if (noNeedDay.equals(ymd)) {
                        flag = true;
                        break;
                    }
                }
            }

            if (flag) {
                continue;
            }

            String week = "";
            try {
                week = HrKit.getWeek(DateUtils.parseDate(ymd, "yyyy-MM-dd"));
            } catch (ParseException e) {
                e.printStackTrace();
            }

            for (String workWeek: workWeekSet) {
                if (week.equals(workWeek)) {
                    shoutWorkDays ++;
                }
            }

        }

        return shoutWorkDays;
    }


    private DepInfoDO getDepInfo(String empInfoId, String siteId) {

        DepInfoDO depInfoDO = null;

        EmpDepQuery empDepQuery = new EmpDepQuery();
        empDepQuery.setEmpId(empInfoId);
        List<EmpDepDO> empDepList = empDepService.selectDO(empDepQuery, siteId);
        if (empDepList.size() <= 0) {
            return depInfoDO;
        }

        // 查询部门信息
        depInfoDO = depInfoService.selectDOById(empDepList.get(0).getDepId(), siteId);

        return depInfoDO;
    }

    /**
     * 根据查询参数，构建example

     * @param attendPeopleMonthlyStatQuery 查询参数
     * @param siteId 所属站点id
     * @return example
     */
    private Example buildExample(AttendPeopleMonthlyStatQuery attendPeopleMonthlyStatQuery, String siteId) {
        Example example = new Example(AttendPeopleMonthlyStatDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (attendPeopleMonthlyStatQuery.getCompanyId() != null) {
            example.and().andLike("companyId", "%" + attendPeopleMonthlyStatQuery.getCompanyId() + "%");
        }
        if (attendPeopleMonthlyStatQuery.getCompanyName() != null) {
            example.and().andLike("companyName", "%" + attendPeopleMonthlyStatQuery.getCompanyName() + "%");
        }
        if (attendPeopleMonthlyStatQuery.getDeptId() != null) {
            example.and().andLike("deptId", "%" + attendPeopleMonthlyStatQuery.getDeptId() + "%");
        }
        if (attendPeopleMonthlyStatQuery.getDeptName() != null) {
            example.and().andLike("deptName", "%" + attendPeopleMonthlyStatQuery.getDeptName() + "%");
        }
        if (attendPeopleMonthlyStatQuery.getAttendPlanId() != null) {
            example.and().andEqualTo("attendPlanId", attendPeopleMonthlyStatQuery.getAttendPlanId());
        }
        if (attendPeopleMonthlyStatQuery.getEmpInfoId() != null) {
            example.and().andLike("empInfoId", "%" + attendPeopleMonthlyStatQuery.getEmpInfoId() + "%");
        }
        if (attendPeopleMonthlyStatQuery.getEmpInfoName() != null) {
            example.and().andLike("empInfoName", "%" + attendPeopleMonthlyStatQuery.getEmpInfoName() + "%");
        }
        if (attendPeopleMonthlyStatQuery.getJobNumber() != null) {
            example.and().andEqualTo("jobNumber", attendPeopleMonthlyStatQuery.getJobNumber());
        }
        if (attendPeopleMonthlyStatQuery.getYearly() != null) {
            example.and().andEqualTo("yearly", attendPeopleMonthlyStatQuery.getYearly());
        }
        if (attendPeopleMonthlyStatQuery.getMonthly() != null) {
            example.and().andEqualTo("monthly", attendPeopleMonthlyStatQuery.getMonthly());
        }
        if (attendPeopleMonthlyStatQuery.getShouldWorkDays() != null) {
            example.and().andEqualTo("shouldWorkDays", attendPeopleMonthlyStatQuery.getShouldWorkDays());
        }
        if (attendPeopleMonthlyStatQuery.getAttendDays() != null) {
            example.and().andEqualTo("attendDays", attendPeopleMonthlyStatQuery.getAttendDays());
        }
        if (attendPeopleMonthlyStatQuery.getRestDays() != null) {
            example.and().andEqualTo("restDays", attendPeopleMonthlyStatQuery.getRestDays());
        }
        if (attendPeopleMonthlyStatQuery.getLateCounts() != null) {
            example.and().andEqualTo("lateCounts", attendPeopleMonthlyStatQuery.getLateCounts());
        }
        if (attendPeopleMonthlyStatQuery.getOnWorkMissCounts() != null) {
            example.and().andEqualTo("onWorkMissCounts", attendPeopleMonthlyStatQuery.getOnWorkMissCounts());
        }
        if (attendPeopleMonthlyStatQuery.getOffWorkMissCounts() != null) {
            example.and().andEqualTo("offWorkMissCounts", attendPeopleMonthlyStatQuery.getOffWorkMissCounts());
        }
        if (attendPeopleMonthlyStatQuery.getAbsenteeismDaysStart() != null &&
                attendPeopleMonthlyStatQuery.getAbsenteeismDaysEnd() != null) {
            example.and().andBetween("absenteeismDays", attendPeopleMonthlyStatQuery.getAbsenteeismDaysStart(),
                    attendPeopleMonthlyStatQuery.getAbsenteeismDaysEnd());
        }
        if (attendPeopleMonthlyStatQuery.getLeaveDaysStart() != null &&
                attendPeopleMonthlyStatQuery.getLeaveDaysEnd() != null) {
            example.and().andBetween("leaveDays", attendPeopleMonthlyStatQuery.getLeaveDaysStart(),
                    attendPeopleMonthlyStatQuery.getLeaveDaysEnd());
        }
        if (attendPeopleMonthlyStatQuery.getGmtCreateStart() != null &&
                attendPeopleMonthlyStatQuery.getGmtCreateEnd() != null) {
            example.and().andBetween("gmtCreate", attendPeopleMonthlyStatQuery.getGmtCreateStart(),
                    attendPeopleMonthlyStatQuery.getGmtCreateEnd());
        }
        if (attendPeopleMonthlyStatQuery.getCreateUserId() != null) {
            example.and().andLike("createUserId", "%" + attendPeopleMonthlyStatQuery.getCreateUserId() + "%");
        }
        if (attendPeopleMonthlyStatQuery.getGmtModifiedStart() != null &&
                attendPeopleMonthlyStatQuery.getGmtModifiedEnd() != null) {
            example.and().andBetween("gmtModified", attendPeopleMonthlyStatQuery.getGmtModifiedStart(),
                    attendPeopleMonthlyStatQuery.getGmtModifiedEnd());
        }
        if (attendPeopleMonthlyStatQuery.getModifiedUserId() != null) {
            example.and().andLike("modifiedUserId", "%" + attendPeopleMonthlyStatQuery.getModifiedUserId() + "%");
        }
        // 排序
        ExampleKit.setExampleOrder(example,attendPeopleMonthlyStatQuery.getOrders());
        return example;
    }
}




